<template>
  <div class="project">
    <a-form
      ref="formRef"
      class="form"
      :model="filterData"
      name="filter"
      autocomplete="off"
    >
      <div class="radio-contanier" v-if="filterFormConfig">
        <a-form-item
          v-for="item in filterFormConfig"
          :key="item.key"
          :label="item.label"
          :name="item.key"
        >
          <a-radio-group
            v-model:value="filterData[item.key || '']"
            optionType="button"
            v-bind="item.props"
            :options="
              [{ label: '全部', value: undefined }].concat(item.props?.options)
            "
            buttonStyle="solid"
          >
          </a-radio-group>
        </a-form-item>
      </div>
      <div class="flex-row">
        <a-form-item name="keyword" style="margin-bottom: 0">
          <a-input
            v-model:value.trim="filterData.keyword"
            style="width: 45vw"
            :placeholder="props.searchPlaceholder || '搜索项目名称'"
          >
            <template #prefix> <search-outlined /> </template>
          </a-input>
        </a-form-item>
        <a-button
          v-if="props.createButtonProps !== undefined"
          type="primary"
          :href="props.createButtonProps.href"
        >
          <plus-outlined />{{ props.createButtonProps.text }}</a-button
        >
      </div>
    </a-form>
    <div
      v-for="item in dataSource"
      :key="item.id"
      class="project-item"
      ref="projectRef"
    >
      <ApprovalStatus :status="item.statusName" />
      <router-link
        class="project-item__title"
        :to="props.detailPath(item) || ''"
      >
        {{ item[props.nameKey] }}
      </router-link>
      <EllipsisText
        class="project-item__desc"
        :text="convert(item[props.descKey])"
        :rows="3"
      ></EllipsisText>
      <a-divider dashed />
      <div class="project-item__extra">
        <slot name="cardFooter" :record="item">
          <p class="indicators">
            <span
              class="indicator-item"
              v-for="indicator in filterFormConfig"
              :key="indicator.key"
              >{{ indicator.label }}：{{
                indicator.map?.[item[indicator.key || ""]]
              }}</span
            >
          </p>
          <p style="flex: none">创建时间：{{ item.createdTime }}</p>
        </slot>
      </div>
    </div>
    <p v-if="pagination.current !== 1 && loading" class="loading-text">
      <a-spin style="display: inline-block" /> 加载中
    </p>
    <a-empty v-else-if="!loading && !dataSource.length" />
  </div>
</template>
<script lang="tsx" setup>
import { debounce, throttle } from "lodash-es";
import { getCurrentInstance, onBeforeUnmount, reactive, ref, watch } from "vue";
import ApprovalStatus from "@/components/ApprovalStatus.vue";
import EllipsisText from "@/components/EllipsisText/EllipsisText.vue";
import { useHtmlToText } from "@/store";
const props = withDefaults(
  defineProps<{
    filterFormConfig?: FormStaticItem[];
    getListMethod: (data: any) => Promise<{
      list: any;
      total: any;
    }>;
    searchPlaceholder?: string;
    nameKey: string;
    descKey: string;
    createButtonProps?: {
      text: string;
      href?: string;
    };
    detailPath: (item: Record<string, any>) => string;
  }>(),
  { nameKey: "projectName", descKey: "projectDesc" }
);
const { convert } = useHtmlToText();
const { $loading } =
  getCurrentInstance()?.appContext?.config.globalProperties || {};
const formRef = ref();
const projectRef = ref();
const loading = ref(false);
const pagination = reactive({
  current: 1,
  pageSize: 20,
  total: 0,
});
const filterData = reactive<Record<string, any>>({});
const dataSource = ref<Record<string, any>>([]);
const getData = async (isInit?: boolean) => {
  if (loading.value || $loading?.loading.value) {
    return;
  }
  try {
    if (isInit) {
      pagination.current = 1;
      $loading?.start();
    } else if (dataSource.value.length < pagination.total) {
      pagination.current++;
    } else {
      return;
    }
    loading.value = true;
    const params = (await formRef.value?.validate()) || filterData.value || {};
    const { current, pageSize } = pagination;
    await props.getListMethod({ current, pageSize, ...params }).then((res) => {
      const { total, list } = res;
      if (pagination.current === 1) dataSource.value = list || [];
      else dataSource.value = dataSource.value.concat(list);
      pagination.total = total;
    });
  } catch (e) {
    console.warn(e);
  } finally {
    loading.value = false;
    $loading?.stop();
  }
};
const getDataDebounce = debounce(getData, 500);
const onScroll = throttle(function () {
  if (!projectRef.value) return;
  const lastIndex = dataSource.value.length - 1;
  const { bottom: nodeBottom } =
    projectRef.value[lastIndex]?.getBoundingClientRect() || {};
  const bottom = window.innerHeight - nodeBottom;
  if (bottom < window.innerHeight / 2) {
    getData();
  }
}, 250);
window.addEventListener("scroll", onScroll);
onBeforeUnmount(() => {
  window.removeEventListener("scroll", onScroll);
});
getData(true);
watch(filterData, () => getDataDebounce(true), { deep: true });
</script>
<style lang="scss" scoped>
.project {
  background-color: #fff;
  border-radius: 4px;
  width: 100%;
  padding: 12px;
  display: flex;
  flex-flow: column nowrap;
  align-items: center;
  & > * {
    width: 100%;
  }
}
.radio-contanier {
  width: 100%;
  border-radius: 5px;
  padding: 12px;
  background-color: rgba(219, 234, 213, 0.3);
  margin-bottom: 16px;
}
:deep(.ant-form-item-label) {
  font-weight: 600;
  margin-right: 30px;
}
.project-item {
  position: relative;
  border: 1px solid $border-color;
  border-radius: 2px;
  padding: 16px;
  padding-right: 100px;
  margin-top: 16px;
  transition: 0.3s;
  &:hover {
    .project-item__title {
      color: $hover-color;
    }
  }
}
.project-item__title {
  @include set-font(20px, $primary-color, 28px);
  font-weight: bold;
  transition: 0.3s;
  &:hover {
    color: $hover-color;
  }
  &:active {
    color: $active-color;
  }
}
.project-item__desc {
  margin-top: 8px;
}
.project-item__extra {
  display: flex;
  flex-flow: row nowrap;
  align-items: flex-start;
  justify-content: space-between;
}
.indicators {
  flex: 1;
}
.indicator-item {
  display: inline-block;
  margin-right: 24px;
}
.loading-text {
  text-align: center;
  margin-top: 24px;
}
</style>
